import { Control } from "ol/control";
import { listen } from "ol/events.js";

/**
 * @typedef {Object} Options
 * @property {function(import("../MapEvent.js").default):void} [render] Function called when the
 * control should be re-rendered. This is called in a `requestAnimationFrame`callback.
 * @property {import("../coordinate.js").CoordinateFormat} [coordinateFormat] Coordinate format.
 * @property {import("../proj.js").ProjectionLike} [projection] Projection. Default is the view projection.
 * @property {string} [className='ol-custom-view-info'] CSS class name.
 * @property {HTMLElement|string} [target] Specify a target if you want the
 * control to be rendered outside of the map's viewport.
 */

/**
 * 信息栏控件类，用于显示地图的实时信息，包括坐标、缩放级别、比例尺、旋转角度和帧率等
 * @extends {import('ol/control').Control}
 */
class InfoBar extends Control {
  /**
   * 创建信息栏控件实例
   * @param {Options} [options={}] 配置选项
   */
  constructor(options = {}) {
    const element = document.createElement("div");
    element.className = options.className || "ol-custom-view-info";

    element.innerHTML = `
    <div class="view-info-content">
        <div class="view-info-content-item longitude">
            经度：120.123456
        </div>
        <div class="view-info-content-item latitude">
            纬度：30.123456
        </div>
        <div class="view-info-content-item zoom">
            缩放级别：10
        </div>
        <div class="view-info-content-item scale">
            比例尺：1:10000
        </div>
        <div class="view-info-content-item direction">
            旋转角：0°
        </div>
        <div class="view-info-content-item FPS">
            帧率：60 FPS
        </div>
    </div>
    `;

    super({
      element: element,
      render: options.render,
      target: options.target,
    });

    this.element_ = element;

    this.animationFrameId = null;
  }

  /**
   * 设置地图实例，并初始化相关事件监听
   * @param {import('ol/Map').default|null} map 地图实例
   * @override
   */
  setMap(map) {
    super.setMap(map);

    if (map) {
      this.listenerKeys.push(
        listen(map, "pointermove", this.handlePointerMove, this),
        listen(map, "moveend", this.handleMoveEnd, this)
      );
      this.updateFPS();
    } else {
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId);
        this.animationFrameId = null;
      }
    }
  }

  /**
   * 处理鼠标移动事件，更新坐标信息
   * @param {import('ol/MapBrowserEvent').default} event 地图浏览器事件
   * @private
   */
  handlePointerMove(event) {
    this.updateCoordinate(event.coordinate);
  }

  /**
   * 处理地图移动结束事件，更新缩放级别、比例尺和旋转角度
   * @param {import('ol/MapEvent').default} event 地图事件
   * @private
   */
  handleMoveEnd(event) {
    this.updateZoom();
    this.updateScale();
    this.updateDirection();
  }

  /**
   * 更新坐标信息显示
   * @param {import('ol/coordinate').Coordinate} coordinate 坐标点
   * @private
   */
  updateCoordinate(coordinate) {
    const projection = this.getMap().getView().getProjection();
    const unit = projection.getUnits();

    const longitudeEl = this.element_.querySelector(".longitude");
    const latitudeEl = this.element_.querySelector(".latitude");

    if (unit === "degrees") {
      longitudeEl.innerHTML = `经度：${coordinate[0].toFixed(6)}`;
      latitudeEl.innerHTML = `纬度：${coordinate[1].toFixed(6)}`;
    } else {
      longitudeEl.innerHTML = `X：${coordinate[0].toFixed(0)}`;
      latitudeEl.innerHTML = `Y：${coordinate[1].toFixed(0)}`;
    }
  }

  /**
   * 更新缩放级别显示
   * @private
   */
  updateZoom() {
    const zoom = this.getMap().getView().getZoom();
    const zoomEl = this.element_.querySelector(".zoom");
    zoomEl.innerHTML = `缩放级别：${zoom.toFixed(0)}`;
  }

  /**
   * 更新比例尺显示
   * @private
   */
  updateScale() {
    const view = this.getMap().getView();
    const resolution = view.getResolution();
    const metersPerUnit = view.getProjection().getMetersPerUnit();

    const scaleDenominator = `1:${(resolution * metersPerUnit).toFixed(0)}`;

    const scaleEl = this.element_.querySelector(".scale");
    scaleEl.innerHTML = `比例尺：${scaleDenominator}`;
  }

  /**
   * 更新旋转角度显示
   * @private
   */
  updateDirection() {
    const direction = this.getMap().getView().getRotation();
    const directionEl = this.element_.querySelector(".direction");
    directionEl.innerHTML = `旋转角：${Math.round(
      (direction * 180) / Math.PI
    )}°`;
  }

  /**
   * 更新帧率显示
   * @private
   */
  updateFPS() {
    let frameCount = 0;
    let startTime = performance.now();

    const frame = () => {
      const now = performance.now();
      const diff = now - startTime;
      frameCount++;
      if (diff >= 1000) {
        const fps = Math.round(frameCount * (1000 / diff));
        const fpsEl = this.element_.querySelector(".FPS");
        fpsEl.innerHTML = `帧率：${fps} FPS`;
        frameCount = 0;
        startTime = now;
      }
      this.animationFrameId = requestAnimationFrame(frame);
    };

    this.animationFrameId = requestAnimationFrame(frame);
  }
}

export default InfoBar;
